package com.baosight.xCyber.input;

import com.alibaba.fastjson.JSONObject;
import com.baosight.hdsdk.HDTagManager;
import com.baosight.hdsdk.common.HDQueryRelation;
import com.baosight.hdsdk.common.HDQueryTagCondition;
import com.baosight.hdsdk.domain.data.HDCommTag;
import com.baosight.hdsdk.exception.HDSdkException;
import com.baosight.xCyber.config.EnvConfig;
import com.baosight.xCyber.dao.IMainNodeMapper;
import com.baosight.xCyber.dao.ITreeNodeMapper;
import com.baosight.xCyber.dao.ITagMapper;
import com.baosight.xCyber.exception.Myexception;
import com.baosight.xCyber.model.TagNode;
import com.baosight.xCyber.util.SqlSessionFactoryUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.text.MessageFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 吴起航
 */
@Component
public class DataLoad {

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private EnvConfig config;

    private static Log logger = LogFactory.getLog(DataLoad.class);

    public Map<String,TagNode> dataMap = new HashMap<>();

    public Map<String,TagNode> mainMap = new LinkedHashMap<>();
            //((o1, o2) -> Integer.compare(dataMap.get(o1).orderNo, dataMap.get(o1).orderNo)));

    public Map<String,TagNode> treeMap = new HashMap<>();

    /**
     * 加载数据库中树的数据节点
     * @return
     */
    public Map<String, TagNode> getDataMap(String treeName) {
        String ihdbServer = config.getIHDBServer();
        String db2Server = config.getDB2Server();
        String tagTable = config.getTagTable();
        //判断db2中是否存在tag表
        if (db2Server != null && tagTable!=null) {
            SqlSession session = SqlSessionFactoryUtil.getSqlSession();
            List<TagNode> db2TagNodes = null;
            try {
                ITagMapper nodeMapper = session.getMapper(ITagMapper.class);
                db2TagNodes = nodeMapper.selectAll();
            } catch (Exception e) {
                logger.error(treeName+":mybatis映射异常："+e.getMessage());
            } finally {
                session.close();
            }
            Map<String,TagNode> map= db2TagNodes
                    .stream()
                    .collect(Collectors.toMap(TagNode::getTagName, Function.identity()));
            dataMap.putAll(map);
            logger.info(treeName+":connect to "+db2Server.split(":")[2]+" success");
            logger.info(treeName+":already loaded db2 data");
        }
        if (config.getIHDBServer() != null) {
            HDTagManager manager = applicationContext.getBean(HDTagManager.class);
            try {
                //获取所有的HDBasicTag
                List<HDCommTag> tagInfo = getAllTagInfo(manager);
                //tags = manager.queryBasicTagsSimple("*", "*", HDTagDataType.ALL, true);
                for (HDCommTag tag : tagInfo) {
                    String tagName=tag.getName();
                    if(!dataMap.containsKey(tagName)){
                        TagNode tagNode = new TagNode();
                        tagNode.id = tag.getId();
                        tagNode.tagName = tagName;
                        tagNode.desc=tag.getDesc();
                        tagNode.source="iHyperDB";
                        tagNode.showName = tag.getName();
                        tagNode.unit = tag.getEngUnits();
                        dataMap.put(tagName,tagNode);
                    }
                }
                logger.info(treeName+":connect to "+ihdbServer+" success");
                logger.info(treeName+":already loaded iHDB data");
            } catch (HDSdkException e) {
                logger.error(treeName+":load iHDB data error:" + e.getMessage());
            }
        }
        return dataMap;
    }

    /**
     * 预先加载数据库中树数据
     */
    public void reloadTreeMap(String treeName){
        String db2Server = config.getDB2Server();
        String treeTable = config.getTreeTable();
        String mainTable = config.getMainTable();
        if (db2Server != null) {
            SqlSession session = SqlSessionFactoryUtil.getSqlSession();
            if (treeTable!=null) {
                ITreeNodeMapper treeNodeMapper = session.getMapper(ITreeNodeMapper.class);
                //treeMap;
                List<Map<String, Object>> stringMap = treeNodeMapper.selectAll(treeName);
                for(Map<String, Object> map: stringMap){
                    TagNode tagNode = TagNode.getTagNode(map);
                    treeMap.put(tagNode.getTagName(),tagNode);
                }
            }
            if(mainTable!=null){
                IMainNodeMapper mainNodeMapper = session.getMapper(IMainNodeMapper.class);
                List<TagNode> nodes = mainNodeMapper.selectAll(treeName);
                nodes.forEach((node)->{
                    mainMap.put(node.getTagName(),node);
                });
            }
            session.close();
            logger.info(treeName+":loading "+treeName+" Tree data");
        }
    }


    /**
     * 持久化存储树结构和数据
     */
    @Transactional(rollbackFor = Myexception.class,
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            timeout = 36000)
    public void saveData(Map<String,TagNode> mainTemp,Map<String,TagNode> treeTemp){
        String db2Server = config.getDB2Server();
        String treeTable = config.getTreeTable();
        String mainTable = config.getMainTable();
        if(mainTemp==null||treeTemp==null||mainTemp.size()==0||treeTemp.size()==0){
            logger.error("数据值为空！");
            return;
        }
        if (db2Server != null){
            SqlSession session = SqlSessionFactoryUtil.getSqlSession();
            int addCount;
            if (treeTable!=null&&treeTemp!=null) {
                addCount = 0;
                ITreeNodeMapper treeNodeMapper = session.getMapper(ITreeNodeMapper.class);
                for(Map.Entry<String,TagNode> entry:treeTemp.entrySet()) {
                    TagNode t = entry.getValue();
                    JSONObject extraParam = new JSONObject();
                    extraParam.put("url","http://10.99.98.207:8080/PDMS/web/SZGJ02/queryForTemplate");
                    t.setExtraParam(extraParam.toJSONString());
                    treeNodeMapper.addNode(t);
                    addCount++;
                    treeMap.put(t.tagName,t);

                }
                session.commit();
                logger.info(MessageFormat.format("有{0}条节点数据缓存至{1}",addCount,treeTable));
            }
            
            if(mainTable!=null&&mainTemp!=null){
                addCount = 0;
                IMainNodeMapper mainNodeMapper = session.getMapper(IMainNodeMapper.class);
                for(Map.Entry<String,TagNode> entry : mainTemp.entrySet()) {
                    TagNode m = entry.getValue();
                    if(m.tagName.equals("")){
                        m.tagName = "root";
                        m.parentId = "";
                    }
                    mainNodeMapper.addNode(m);
                    addCount++;
                    mainMap.put(m.tagName,m);
                }
                session.commit();
                logger.info(MessageFormat.format("有{0}条节点数据缓存至{1}",addCount,mainTable));
            }
            session.close();
        }
    }

    /**
     * 清除树的服务
     * @param treeName 树的名称
     * @return 成功是否的字符串
     */
    @Transactional(rollbackFor = Myexception.class,
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            timeout = 36000)
    public String deleteTree(String treeName) {

        int m=-1,t=-1;
        if (config.getDB2Server() != null && treeName != null) {
            SqlSession session = SqlSessionFactoryUtil.getSqlSession();
            try {
                IMainNodeMapper mainNodeMapper = session.getMapper(IMainNodeMapper.class);
                ITreeNodeMapper treeNodeMapper = session.getMapper(ITreeNodeMapper.class);
                m=mainNodeMapper.deleteTree(treeName);
                t=treeNodeMapper.deleteTree(treeName);
            } finally {
                session.commit();
                session.close();
            }
        }
        return m>0&&t>0?treeName+"数据清除成功":treeName+"数据清除失败";
    }

    /**
     * 模糊搜索全部tag数据
     * @param tagManager
     * @return tag点数据集
     * @throws HDSdkException
     */
    private List<HDCommTag> getAllTagInfo(HDTagManager tagManager) throws HDSdkException {
        long tagClassMask=47;
        long propMark= 4294967296L*2-1;
        HDQueryTagCondition hdQueryTagCondition = new HDQueryTagCondition();
        hdQueryTagCondition.setQueryRelation(HDQueryRelation.LIKE);
        hdQueryTagCondition.setQueryValue("*");
        hdQueryTagCondition.setTagPropID((byte) 1);
        List<HDQueryTagCondition> queryConditions = new ArrayList<HDQueryTagCondition>(){{
            add(hdQueryTagCondition);
        }};
        return tagManager.queryTagsByConds(queryConditions,tagClassMask,propMark);
    }
}
